Imports System.Windows.Forms
Imports System.Drawing

Public Class Socket
    Inherits Control
    Private M_Border As Integer = 1
    Private M_Border_offset As Integer = 1
    Private M_Ring As Integer = 5
    Private M_Radius As Integer = 5
    Private M_SocketType As Socket_Type = Socket_Type.None
    Private M_SocketDir As Socket_Direction = Socket_Direction.Bidirectional
    Private M_Enabled As Boolean = False
    Private M_Data As Object = Nothing
    Private RemoteSocket As Socket
    Private M_Connect As Boolean = False
    Private M_Exit_to As Exit_Side = Exit_Side.None
    Private M_Center_Point As Point
    Private M_Color As Color = Color.AliceBlue
    Private LR As LineRouter = Nothing
    Private M_LR As Boolean = False
    Public Event NewData(ByVal data As Object)
    Public Event Connect()
    Public Event Disconnected()
    Private M_Link_Led As Led
    Private M_Act_Led As Led
    Public Event EnableStateChanged(ByVal State As Boolean)
    Private M_Hilited As Boolean = False
    Private M_Selected As Boolean = False
    Private M_Info As SocketInfo
    Public Event SelectMe(ByVal Sock As Socket)
    Public Event HiLite(ByVal Sock As Socket)
    Public Event LoLite(ByVal Sock As Socket)

    'Special
    Private M_Busy As Boolean
    Private M_Value As Object
    Public Event NewValue(ByVal Value As Object)
    Public Event BusyStateChanged(ByVal NewState As Boolean)
    Private SocketTypesColor As New SocketTypes

    Enum Socket_Type
        None = 0
        Video = 1
        Trigger = 2
        Image = 3
        CameraControl = 4
        Control = 5
        Universal = 6
        HardwarePort = 7
        Selected = 10
    End Enum
    Enum Socket_Direction
        Output = 0
        Input = 1
        Bidirectional = 2
    End Enum
    Enum Exit_Side
        None = 0
        To_Top = 1
        To_Bottom = 2
        To_Left = 3
        To_Right = 4
    End Enum
    Public Property LinkLED() As Led
        Get
            Return M_Link_Led
        End Get
        Set(ByVal value As Led)
            M_Link_Led = value
            UpdateLed()
        End Set
    End Property
    Public Property ActLED() As Led
        Get
            Return M_Act_Led
        End Get
        Set(ByVal value As Led)
            M_Act_Led = value
            UpdateLed()
        End Set
    End Property
    Public Property Radius() As Integer
        Get
            Return M_Radius
        End Get
        Set(ByVal value As Integer)
            M_Radius = value
            Me.Refresh()
        End Set
    End Property
    Public Property SocketType() As Socket_Type
        Get
            Return M_SocketType
        End Get
        Set(ByVal value As Socket_Type)
            M_SocketType = value
            Me.Refresh()
        End Set
    End Property
    Public Property SocketDirection() As Socket_Direction
        Get
            Return M_SocketDir
        End Get
        Set(ByVal value As Socket_Direction)
            M_SocketDir = value
            Me.Refresh()
        End Set
    End Property
    Public Property SocketsEnable() As Boolean
        Get
            Return M_Enabled
        End Get
        Set(ByVal value As Boolean)
            If M_Connect = True Then
                If Remote IsNot Nothing Then
                    Remote.SetEnable = value
                End If
                M_Enabled = value
                UpdateLed()
                RaiseEvent EnableStateChanged(M_Enabled)
            End If
        End Set
    End Property
    Public WriteOnly Property SetEnable() As Boolean
        Set(ByVal value As Boolean)
            If M_Connect = True Then
                M_Enabled = value
                UpdateLed()
                RaiseEvent EnableStateChanged(M_Enabled)
            End If
        End Set
    End Property
    Public Property ExitTo() As Exit_Side
        Get
            Return M_Exit_to
        End Get
        Set(ByVal value As Exit_Side)
            M_Exit_to = value
        End Set
    End Property
    Public ReadOnly Property CenterPoint() As Point
        Get
            Dim SP As New Point(Me.Parent.Location.X + Me.Location.X + (Me.Width / 2), Me.Parent.Location.Y + Me.Location.Y + (Me.Height / 2))
            Return SP
        End Get
    End Property
    Public Sub Reposition()
        If M_Connect = True Then
            If M_LR = True Then
                LR.RePosition()
            Else
                Remote.Reposition()
            End If
        End If
    End Sub
    Public ReadOnly Property SocketColor() As Color
        Get
            Return M_Color
        End Get
    End Property

    Public Property Remote() As Socket
        Get
            Return RemoteSocket
        End Get
        Set(ByVal value As Socket)
            RemoteSocket = value
        End Set
    End Property

    Private Sub Button3D_ForeColorChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.ForeColorChanged
        Me.Refresh()
    End Sub

    Private Sub Socket_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
        If M_SocketType = Socket_Type.None Or M_SocketType = Socket_Type.Universal Then Exit Sub
        If M_Connect = False Then
            M_Selected = True
            Me.Refresh()
            RaiseEvent SelectMe(Me)
        End If
    End Sub
    Public Property Selected()
        Get
            Return M_Selected
        End Get
        Set(ByVal value)
            M_Selected = value
        End Set
    End Property
    Public Sub UnSelect()
        M_Selected = False
        M_Hilited = False
        Me.Refresh()
        If M_Info IsNot Nothing Then M_Info.Dispose()
    End Sub
    Private Sub Socket_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter
        If Me.Connected = False And M_Selected = False Then
            M_Hilited = True
            Me.Refresh()
            M_Info = New SocketInfo
            M_Info.Socket = Me
            M_Info.Visible = False
            Dim L As New Point(Me.CenterPoint.X - (M_Info.Width / 2), Me.CenterPoint.Y - M_Info.Height - 20)
            Me.Parent.Parent.Controls.Add(M_Info)
            M_Info.Location = L
            M_Info.BackColor = Me.SocketColor
            M_Info.BringToFront()
            M_Info.Visible = True
            RaiseEvent HiLite(Me)
        End If
    End Sub

    Private Sub Socket_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
        If Me.Connected = False And M_Selected = False Then
            M_Hilited = False
            Me.Refresh()
            M_Info.Dispose()
            RaiseEvent LoLite(Me)
        End If
    End Sub

    Private Sub button2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
        Dim BP As New Bitmap(Me.Width, Me.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        Dim g As Graphics = Graphics.FromImage(BP)
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
        g.Clear(Color.Transparent)
        Dim Border As Integer = M_Border

        Dim x As Integer = (Me.Width / 2) - M_Radius - M_Ring
        Dim y As Integer = (Me.Height / 2) - M_Radius - M_Ring
        Dim w As Integer = (M_Radius * 2) + (M_Ring * 2)
        Dim h As Integer = (M_Radius * 2) + (M_Ring * 2)
        Dim TC As Color = SocketTypesColor.GetBodyColor(M_SocketType)
        'If M_SocketType = Socket_Type.None Then TC = Color.Gray
        'If M_SocketType = Socket_Type.Video Then TC = Color.Yellow
        'If M_SocketType = Socket_Type.Trigger Then TC = Color.DodgerBlue
        'If M_SocketType = Socket_Type.Universal Then TC = Color.White
        'If M_SocketType = Socket_Type.Image Then TC = Color.Green
        'If M_SocketType = Socket_Type.Control Then TC = Color.Orange
        'If M_SocketType = Socket_Type.CameraControl Then TC = Color.Maroon
        'If M_SocketType = Socket_Type.HardwarePort Then TC = Color.DeepPink
        M_Color = TC
        If M_Hilited = True Or M_Selected = True Then
            TC = Color.FromArgb(255, 0, 0)
        End If
        'Dim TCb As Color
        Dim TCb As Color = SocketTypesColor.GetIdentColor(M_SocketType)
        'If M_SocketType = Socket_Type.None Then TCb = Color.Gray
        'If M_SocketType = Socket_Type.Video Then TCb = Color.Yellow
        'If M_SocketType = Socket_Type.Trigger Then TCb = Color.DodgerBlue
        'If M_SocketType = Socket_Type.Universal Then TCb = Color.White
        'If M_SocketType = Socket_Type.Image Then TCb = Color.HotPink
        'If M_SocketType = Socket_Type.Control Then TCb = Color.Orange
        'If M_SocketType = Socket_Type.CameraControl Then TCb = Color.Maroon
        'If M_SocketType = Socket_Type.HardwarePort Then TCb = Color.DeepPink
        If M_Hilited = True Or M_Selected = True Then
            TCb = Color.FromArgb(255, 0, 0)
        End If
        Dim Br As New SolidBrush(TC)
        g.FillEllipse(Br, x, y, w, h)
        Dim Pb As New Pen(TCb, 4)
        Dim Lx As Integer = x + (w / 2)
        Dim Ly As Integer = y + (h / 2)
        Dim Lh = (M_Radius * 2)
        Dim Lw = (M_Radius * 2)
        g.DrawLine(Pb, Lx, y, Lx, h + y)
        g.DrawLine(Pb, x, Ly, w + x, Ly)
        g.DrawEllipse(Pens.Black, x, y, w, h)
        Dim x2 As Integer = (Me.Width / 2) - M_Radius
        Dim y2 As Integer = (Me.Height / 2) - M_Radius
        Dim w2 As Integer = (M_Radius * 2)
        Dim h2 As Integer = (M_Radius * 2)
        If M_Hilited = True Or M_Selected = True Then
            g.FillEllipse(Br, x2, y2, w2, h2)
            g.DrawEllipse(Pens.Black, x2, y2, w2, h2)
        Else
            g.FillEllipse(Brushes.Black, x2, y2, w2, h2)
        End If

        w = BP.Width
        h = BP.Height
        e.Graphics.DrawImage(BP, 0, 0, w, h)

    End Sub
    Private Sub Button3D_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
        Me.Width = 30
        Me.Height = 30
    End Sub
    Public Sub New()
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        Me.BackColor = Color.Transparent
        Me.AllowDrop = True
    End Sub
    Public Property Border() As Integer
        Get
            Return M_Border
        End Get
        Set(ByVal value As Integer)
            M_Border = value
            Me.Refresh()
        End Set
    End Property
    Public Property BorderOffset() As Integer
        Get
            Return M_Border_offset
        End Get
        Set(ByVal value As Integer)
            M_Border_offset = value
            Me.Refresh()
        End Set
    End Property
    Public Property Ring() As Integer
        Get
            Return M_Ring
        End Get
        Set(ByVal value As Integer)
            M_Ring = value
            Me.Refresh()
        End Set
    End Property
    Private Sub PlugDisconnect(ByVal sender As Object)
        LR.Dispose()
        LR = Nothing
        M_Connect = False
        M_Enabled = False
        Remote.RemoteDisconnect()
        RaiseEvent Disconnected()
        RaiseEvent EnableStateChanged(M_Enabled)
        UpdateLed()
    End Sub
    Public Sub RemoteDisconnect()
        M_Connect = False
        M_Enabled = False
        RaiseEvent Disconnected()
        RaiseEvent EnableStateChanged(M_Enabled)
        UpdateLed()
    End Sub
    Public Sub Disconnect()
        If LR Is Nothing Then
            Remote.PlugDisconnect(Me)
        Else
            PlugDisconnect(Me)
        End If
    End Sub
    Private Sub UpdateLed()
        If M_Link_Led IsNot Nothing Then
            If M_Connect = True Then
                M_Link_Led.State = Led.LedState.Led_On
            Else
                M_Link_Led.State = Led.LedState.Led_Off
            End If
        End If
        If M_Act_Led IsNot Nothing Then
            If M_Connect = True Then
                If M_Enabled = True Then
                    M_Act_Led.State = Led.LedState.Led_On
                Else
                    M_Act_Led.State = Led.LedState.Led_Off
                End If
            Else
                M_Act_Led.State = Led.LedState.Led_Off
            End If
        End If
    End Sub
    Public ReadOnly Property Connected() As Boolean
        Get
            Return M_Connect
        End Get
    End Property
    Public Sub ConnectTo(ByVal Sock As Socket, Optional ByVal Points As String = "")
        Debug.Print("SocP:" & Points)
        If M_Connect = False Then
            If Sock.SocketType = Me.SocketType Or Sock.SocketType = Socket_Type.Universal Then
                If Me.SocketType = Socket_Type.Universal Then Me.SocketType = Sock.SocketType
                RemoteSocket = Sock
                RemoteSocket.ConnectFrom(Me)
                RaiseEvent Connect()
                M_Connect = True
                Me.Parent.Parent.SuspendLayout()
                LR = New LineRouter
                Me.Parent.Parent.Controls.Add(LR)
                LR.Socket1 = Me
                LR.Socket2 = RemoteSocket
                LR.DrawWire()
                If Points > "" Then
                    LR.AddPoints(Points)
                End If
                Me.Parent.Parent.ResumeLayout()
                AddHandler LR.Disconnect, AddressOf PlugDisconnect
                M_LR = True
            End If
        End If
        Me.Refresh()
        UpdateLed()
    End Sub
    Public Sub ConnectFrom(ByVal Sock As Socket)
        If M_Connect = False Then
            If Sock.SocketType = Me.SocketType Or Me.SocketType = Socket_Type.Universal Then
                If Me.SocketType = Socket_Type.Universal Then Me.SocketType = Sock.SocketType
                RemoteSocket = Sock
                RaiseEvent Connect()
                M_Connect = True
            End If
        End If
        Me.Refresh()
        UpdateLed()
    End Sub
    Public Function GetLinePoints() As String
        Dim S As String
        If LR IsNot Nothing Then
            S = LR.GetPoints
        Else
            S = RemoteSocket.GetLinePoints
        End If
        Return S
    End Function

    Public Property Busy() As Boolean
        Get
            Return M_Busy
        End Get
        Set(ByVal value As Boolean)
            M_Busy = value
            If Remote IsNot Nothing Then
                If Remote.Busy <> M_Busy Then
                    Remote.Busy = M_Busy
                End If
            End If
            RaiseEvent BusyStateChanged(M_Busy)
        End Set
    End Property
    Public Property Value() As Object
        Get
            Return M_Value
        End Get
        Set(ByVal value As Object)
            M_Value = value
            If Remote IsNot Nothing Then
                Remote.SetValue(value)
            End If
            RaiseEvent NewValue(M_Value)
        End Set
    End Property
    Public Sub SetValue(ByVal Value As Object)
        M_Value = Value
        RaiseEvent NewValue(Value)
    End Sub
End Class
